<template>
    <div class="bar-chart-container">
        <div ref="chartRef" class="chart" :style="{ height: height + 'px' }"></div>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import * as echarts from 'echarts'

// 定义指标配置接口
interface SeriesConfig {
    key: string           // 数据字段名
    name: string          // 显示名称
    color?: string        // 柱状图颜色
    barWidth?: string | number  // 柱状图宽度
    itemStyle?: any       // 样式配置
}

// 定义坐标轴配置接口
interface AxisConfig {
    name: string          // 坐标轴名称
    type?: 'category' | 'value' | 'time' | 'log'
    data?: any[]          // 分类数据
    min?: number | string // 最小值
    max?: number | string // 最大值
    axisLabel?: any       // 标签样式
    axisLine?: any        // 轴线样式
    splitLine?: any       // 分割线样式
}

// 定义组件属性
interface Props {
    // 图表数据
    data: Array<Record<string, any>>
    // 横坐标配置
    xAxis?: AxisConfig
    // 纵坐标配置
    yAxis?: AxisConfig
    // 指标配置数组
    series: SeriesConfig[]
    // 图表标题
    title?: string
    // 图表高度
    height?: number
    // 是否显示网格
    showGrid?: boolean
    // 是否显示数据标签
    showLabel?: boolean
    // 是否显示图例
    showLegend?: boolean
    // 是否启用缩放
    enableZoom?: boolean
    // 是否显示工具箱
    showToolbox?: boolean
    // 图例位置
    legendPosition?: 'top' | 'bottom' | 'left' | 'right'
    // 网格配置
    grid?: {
        left?: string | number
        right?: string | number
        top?: string | number
        bottom?: string | number
    }
    // 柱状图方向
    direction?: 'horizontal' | 'vertical'
    // 是否堆叠
    stack?: boolean
    // 柱状图间距
    barGap?: string
    // 柱状图组间距
    barCategoryGap?: string
}

// 设置默认值
const props = withDefaults(defineProps<Props>(), {
    title: '',
    height: 400,
    showGrid: true,
    showLabel: false,
    showLegend: true,
    enableZoom: false,
    showToolbox: false,
    legendPosition: 'top',
    direction: 'vertical',
    stack: false,
    barGap: '30%',
    barCategoryGap: '20%',
    grid: () => ({
        left: '3%',
        right: '4%',
        bottom: '3%',
        top: 50
    })
})

// 图表引用
const chartRef = ref<HTMLElement>()
let chartInstance: echarts.ECharts | null = null

// 初始化图表
const initChart = () => {
    if (!chartRef.value) return

    // 创建 ECharts 实例
    chartInstance = echarts.init(chartRef.value)

    // 设置图表配置
    const option = getChartOption()
    chartInstance.setOption(option)

    // 监听窗口大小变化
    window.addEventListener('resize', handleResize)
}

// 获取图表配置
const getChartOption = () => {
    const isHorizontal = props.direction === 'horizontal'
    
    // 处理坐标轴数据
    const xAxisData = props.xAxis?.data || props.data.map(item => item.name || item[Object.keys(item)[0]])
    
    // 处理指标系列
    const series = props.series.map((config, index) => {
        const seriesData = props.data.map(item => item[config.key] || 0)
        
        return {
            name: config.name,
            type: 'bar',
            data: seriesData,
            stack: props.stack ? 'total' : undefined,
            barWidth: config.barWidth || '60%',
            barGap: props.barGap,
            barCategoryGap: props.barCategoryGap,
            itemStyle: {
                color: config.color || ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399'][index % 5],
                borderRadius: [4, 4, 0, 0],
                ...config.itemStyle
            },
            label: props.showLabel ? {
                show: true,
                position: isHorizontal ? 'right' : 'top',
                color: '#666',
                fontSize: 12
            } : undefined
        }
    })

    // 获取图例数据
    const legendData = props.series.map(config => config.name)

    // 计算网格位置
    const gridTop = props.title ? (props.grid?.top || 80) : (props.grid?.top || 50)
    const gridBottom = props.enableZoom ? (props.grid?.bottom || 60) : (props.grid?.bottom || 30)

    const option: echarts.EChartsOption = {
        title: props.title ? {
            text: props.title,
            left: 'center',
            textStyle: {
                fontSize: 16,
                fontWeight: 'bold',
                color: '#333'
            }
        } : undefined,

        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'shadow',
                label: {
                    backgroundColor: '#6a7985'
                }
            },
            formatter: (params: any) => {
                let result = `${params[0].name}<br/>`
                params.forEach((param: any) => {
                    result += `${param.seriesName}: ${param.value}<br/>`
                })
                return result
            }
        },

        legend: props.showLegend ? {
            data: legendData,
            top: props.legendPosition === 'top' ? (props.title ? 40 : 10) : undefined,
            bottom: props.legendPosition === 'bottom' ? 10 : undefined,
            left: props.legendPosition === 'left' ? 10 : 'center',
            right: props.legendPosition === 'right' ? 10 : undefined
        } : undefined,

        grid: {
            left: props.grid?.left || '3%',
            right: props.grid?.right || '4%',
            bottom: gridBottom,
            top: gridTop,
            containLabel: true
        },

        toolbox: props.showToolbox ? {
            feature: {
                saveAsImage: {},
                dataZoom: {},
                restore: {}
            },
            right: 20,
            top: 20
        } : undefined,

        xAxis: isHorizontal ? {
            type: props.yAxis?.type || 'value',
            name: props.yAxis?.name,
            min: props.yAxis?.min,
            max: props.yAxis?.max,
            axisLabel: {
                color: '#666',
                ...props.yAxis?.axisLabel
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd',
                    ...props.yAxis?.axisLine?.lineStyle
                },
                ...props.yAxis?.axisLine
            },
            splitLine: props.showGrid ? {
                show: true,
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed',
                    ...props.yAxis?.splitLine?.lineStyle
                },
                ...props.yAxis?.splitLine
            } : {
                show: false
            }
        } : {
            type: props.xAxis?.type || 'category',
            name: props.xAxis?.name,
            data: xAxisData,
            min: props.xAxis?.min,
            max: props.xAxis?.max,
            axisLabel: {
                color: '#666',
                ...props.xAxis?.axisLabel
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd',
                    ...props.xAxis?.axisLine?.lineStyle
                },
                ...props.xAxis?.axisLine
            },
            splitLine: props.showGrid ? {
                show: true,
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed',
                    ...props.xAxis?.splitLine?.lineStyle
                },
                ...props.xAxis?.splitLine
            } : {
                show: false
            }
        },

        yAxis: isHorizontal ? {
            type: props.xAxis?.type || 'category',
            name: props.xAxis?.name,
            data: xAxisData,
            min: props.xAxis?.min,
            max: props.xAxis?.max,
            axisLabel: {
                color: '#666',
                ...props.xAxis?.axisLabel
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd',
                    ...props.xAxis?.axisLine?.lineStyle
                },
                ...props.xAxis?.axisLine
            },
            splitLine: props.showGrid ? {
                show: true,
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed',
                    ...props.xAxis?.splitLine?.lineStyle
                },
                ...props.xAxis?.splitLine
            } : {
                show: false
            }
        } : {
            type: props.yAxis?.type || 'value',
            name: props.yAxis?.name,
            min: props.yAxis?.min,
            max: props.yAxis?.max,
            axisLabel: {
                color: '#666',
                ...props.yAxis?.axisLabel
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd',
                    ...props.yAxis?.axisLine?.lineStyle
                },
                ...props.yAxis?.axisLine
            },
            splitLine: props.showGrid ? {
                show: true,
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed',
                    ...props.yAxis?.splitLine?.lineStyle
                },
                ...props.yAxis?.splitLine
            } : {
                show: false
            }
        },

        series: series,

        dataZoom: props.enableZoom ? [
            {
                type: 'inside',
                start: 0,
                end: 100
            },
            {
                show: true,
                type: 'slider',
                bottom: 10
            }
        ] : undefined
    }

    return option
}

// 更新图表数据
const updateChart = () => {
    if (chartInstance) {
        const option = getChartOption()
        chartInstance.setOption(option, true)
    }
}

// 处理窗口大小变化
const handleResize = () => {
    if (chartInstance) {
        chartInstance.resize()
    }
}

// 销毁图表
const destroyChart = () => {
    if (chartInstance) {
        chartInstance.dispose()
        chartInstance = null
    }
    window.removeEventListener('resize', handleResize)
}

// 监听数据变化
watch(() => props.data, () => {
    nextTick(() => {
        updateChart()
    })
}, { deep: true })

// 监听其他属性变化
watch([
    () => props.title,
    () => props.showGrid,
    () => props.showLabel,
    () => props.showLegend,
    () => props.enableZoom,
    () => props.showToolbox,
    () => props.legendPosition,
    () => props.grid,
    () => props.xAxis,
    () => props.yAxis,
    () => props.series,
    () => props.direction,
    () => props.stack,
    () => props.barGap,
    () => props.barCategoryGap
], () => {
    nextTick(() => {
        updateChart()
    })
})

// 组件挂载时初始化图表
onMounted(() => {
    nextTick(() => {
        initChart()
    })
})

// 组件卸载时销毁图表
onUnmounted(() => {
    destroyChart()
})

// 暴露方法给父组件
defineExpose({
    updateChart,
    resize: handleResize
})
</script>

<style scoped>
.bar-chart-container {
    width: 100%;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    overflow: hidden;
}

.chart {
    width: 100%;
    min-height: 300px;
}
</style>
